-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
C#: Models for higher order methods. #17742
C#: Models for higher order methods. #17742
Conversation
f25e44b
to
21a0f76
Compare
cb0b639
to
eb1c4e9
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall LGTM. Some comments, mainly related to CFG splitting.
TCapturedVariableContent(VariableCapture::CapturedVariable v) | ||
TCapturedVariableContent(VariableCapture::CapturedVariable v) or | ||
TDelegateCallArgumentContent(int i) { | ||
i = [0 .. max(int j | j = any(DelegateCall dc).getNumberOfArguments())] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: max(any(DelegateCall dc).getNumberOfArguments()) - 1
.
* If there is a delegate call f(x), then we store "x" on "f" | ||
* using a delegate argument content set. | ||
*/ | ||
private predicate storeStepDelegateCall(Node node1, ContentSet c, Node node2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation does not properly take CFG splitting into account. I think the following works:
private predicate storeStepDelegateCall(ExplicitArgumentNode node1, ContentSet c, Node node2) {
exists(ExplicitDelegateLikeDataFlowCall call, int i |
node1.argumentOf(call, TPositionalArgumentPosition(i)) and
lambdaCall(call, _, node2.(PostUpdateNode).getPreUpdateNode()) and
c.isDelegateCallArgument(i)
)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Uh, thx!
Could you elaborate a bit on, which cases are now covered that wasn't covered before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The old implementation had the issue that it could potentially mix CFG nodes belonging to different CFG splits. Moreover, using DelegateLikeCall
instead of just DelegateCall
means that function pointers are also taken into account.
* If there is a delegate call f(x), then we read the return of the delegate | ||
* call. | ||
*/ | ||
private predicate readStepDelegateCall(Node node1, ContentSet c, Node node2) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, because of CFG splitting:
private predicate readStepDelegateCall(Node node1, ContentSet c, OutNode node2) {
exists(ExplicitDelegateLikeDataFlowCall call |
lambdaCall(call, _, node1) and
node2.getCall(TNormalReturnKind()) = call and
c.isDelegateCallReturn()
)
}
// neutral=Models;HigherOrderParameters;Map;(System.Func<System.Object,System.Object>,System.Object);summary;df-generated | ||
// contentbased-summary=Models;HigherOrderParameters;false;Map;(System.Func<System.Object,System.Object>,System.Object);;Argument[1];Argument[0].Parameter[0];value;dfc-generated | ||
// contentbased-summary=Models;HigherOrderParameters;false;Map;(System.Func<System.Object,System.Object>,System.Object);;Argument[0].ReturnValue;ReturnValue;value;dfc-generated | ||
public object Map(Func<object, object> f, object o) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Apply
would be a more appropriate name.
// neutral=Models;HigherOrderParameters;Map2;(System.Object,System.Func<System.Object,System.Object,System.Object>);summary;df-generated | ||
// contentbased-summary=Models;HigherOrderParameters;false;Map2;(System.Object,System.Func<System.Object,System.Object,System.Object>);;Argument[0];Argument[1].Parameter[1];value;dfc-generated | ||
// contentbased-summary=Models;HigherOrderParameters;false;Map2;(System.Object,System.Func<System.Object,System.Object,System.Object>);;Argument[1].ReturnValue;ReturnValue;value;dfc-generated | ||
public object Map2(object o, Func<object, object, object> f) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same
} | ||
|
||
/** | ||
* Models as Data currently doesn't support callback logic in fields. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think that's true: For example, I would expect something like this to work just fine:
input = Argument[0].Field[Foo].ReturnValue
output = ReturnValue
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried that but it didn't work. Furthermore, if Foo
is a synthetic field some of the data flow consistency tests start failing. Due to time constraints (and since wasn't that many summaries), I just decided to remove the problematic summaries from the output.
In any case, I will change the wording.
…synthetic fields.
eb1c4e9
to
e9c9519
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just one last thing.
@@ -1149,7 +1149,7 @@ private module Cached { | |||
} or | |||
TCapturedVariableContent(VariableCapture::CapturedVariable v) or | |||
TDelegateCallArgumentContent(int i) { | |||
i = [0 .. max(int j | j = any(DelegateCall dc).getNumberOfArguments())] | |||
i = [0 .. max(any(DelegateCall dc).getNumberOfArguments())] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still missing the - 1
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, you are right! Thank you for paying close attention!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suppose we also want to consider DelegateLikeCall instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, yes.
In this PR we added support for read/store steps for delegate calls (where the delegate being called is parameter of a callable) for C#.
The read and store steps for delegate calls and delegate returns are basically "dead ends" and are only relevant for content dataflow related to model generation.